"""
    简单的画板4.0
    功能：
        将按住鼠标后移动的轨迹保留在窗体上
        并解决二次作画时与上次痕迹连续的问题
    作者：PyLearn
    博客: http://www.cnblogs.com/PyLearn/
    最后修改日期: 2017/10/18
"""
import sys

from PyQt5 import QtGui, QtWidgets, QtCore
from PyQt5.QtWidgets import (QApplication, QWidget)
from PyQt5.QtGui import (QPainter, QPen, QCursor)
from PyQt5.QtCore import Qt
import operator


class Eraser(QApplication):
    def __init__(self):
        super().__init__([])
        QApplication.setOverrideCursor(QCursor(QtGui.QPixmap('eraser.png')))
        self.pyqt_learn = Example()
        self.pyqt_learn.show()
        self.pyqt_learn.button.clicked.connect(self.get_screenshot)

    def get_screenshot(self):
        screen = QApplication.primaryScreen()
        img = screen.grabWindow(self.pyqt_learn.winId()).toImage()
        img.save("screenshot.jpg")


class Example(QWidget):

    def __init__(self):
        super(Example, self).__init__()

        # resize设置宽高，move设置位置
        self.resize(400, 300)
        self.move(100, 100)
        self.setWindowTitle("简单的画板4.0")

        # setMouseTracking设置为False，否则不按下鼠标时也会跟踪鼠标事件
        self.setMouseTracking(False)

        '''
            要想将按住鼠标后移动的轨迹保留在窗体上
            需要一个列表来保存所有移动过的点
        '''
        self.pos_xy = []
        for i in range(100):
            self.pos_xy.append((i, i))
        self.pos_xy.append((-1, -1))

        self.button = QtWidgets.QPushButton(self)
        self.button.setGeometry(QtCore.QRect(100, 100, 50, 50))

    def paintEvent(self, event):
        painter = QPainter()
        painter.begin(self)
        pen = QPen(Qt.black, 2, Qt.SolidLine)
        painter.setPen(pen)

        '''
            首先判断pos_xy列表中是不是至少有两个点了
            然后将pos_xy中第一个点赋值给point_start
            利用中间变量pos_tmp遍历整个pos_xy列表
                point_end = pos_tmp

                判断point_end是否是断点，如果是
                    point_start赋值为断点
                    continue
                判断point_start是否是断点，如果是
                    point_start赋值为point_end
                    continue

                画point_start到point_end之间的线
                point_start = point_end
            这样，不断地将相邻两个点之间画线，就能留下鼠标移动轨迹了
        '''
        if len(self.pos_xy) > 1:
            point_start = self.pos_xy[0]
            for pos_tmp in self.pos_xy:
                point_end = pos_tmp

                if point_end == (-1, -1):
                    point_start = (-1, -1)
                    continue
                if point_start == (-1, -1):
                    point_start = point_end
                    continue

                painter.drawLine(point_start[0], point_start[1], point_end[0], point_end[1])
                point_start = point_end
        painter.end()

    def mouseMoveEvent(self, event):
        '''
            按住鼠标移动事件：将当前点添加到pos_xy列表中
            调用update()函数在这里相当于调用paintEvent()函数
            每次update()时，之前调用的paintEvent()留下的痕迹都会清空
        '''
        ''' 橡皮擦，简单的实现将所有范围内的列表内像素改为（-1， -1）'''
        pos_tmp = (event.pos().x(), event.pos().y())
        range_erase = 5
        # 将橡皮擦范围内的点赋值为（-1， -1）
        for i in range(self.pos_xy.__len__()):
            if (self.pos_xy[i][0] - pos_tmp[0]) ** 2 + (self.pos_xy[i][1] - pos_tmp[1]) ** 2 < range_erase ** 2:
                self.pos_xy[i] = (-1, -1)
        imin = -1
        # 缩短数组，合并相邻的（-1，-1）
        for i in range(self.pos_xy.__len__()):
            if i < self.pos_xy.__len__() and operator.eq(self.pos_xy[i], (-1, -1)) and imin == -1:
                imin = i
            elif i < self.pos_xy.__len__() and imin != -1 and not operator.eq(self.pos_xy[i], (-1, -1)):
                if i - 1 > imin != -1:
                    del self.pos_xy[imin + 1:i]
                imin = -1

        self.update()


if __name__ == "__main__":
    app = Eraser()
    sys.exit(app.exec_())
